#include "TestFun.h"
#include <set>
#include <map>
#include <functional>

#include "HardFun5_1.h"
#include "EasyFunAny_1.h"
#include "CEC2017_F1.h"
#include "CEC2017_F2.h"
#include "CEC2017_F3.h"
#include "CEC2017_F4.h"
#include "CEC2017_F5.h"
#include "CEC2017_F6.h"
#include "CEC2017_F9.h"

#include "NIST_Gauss3.h"
#include "DumpLog.h"
namespace Solver
{

Test::Test()
{

}

Test::~Test()
{

}

std::shared_ptr<BaseFun> Test::getFun(FunType_E type, std::size_t dim)
{
    auto mapFun = getFunMap();
    auto it = mapFun.find(type);
    if (it == mapFun.end())
    {
        LogError("没有类型初始化函数, ", (int)type);
        return nullptr;
    }
    else
    {
        return it->second(dim);
    }
}

vecBaseFun_t Test::getFuns(const vecFunType_t funTypes, std::size_t dim)
{
    //1.
    auto mapFun = getFunMap();
    std::set<FunType_E> setFun;
    vecBaseFun_t vecFun;
    for (auto tp : funTypes)
    {
        //1.1
        auto it = mapFun.find(tp);
        if (it == mapFun.end())
        {
            LogError("没有类型初始化函数:" + std::to_string((int)tp));
            continue;
        }

        //1.2
        setFun.insert(tp);

        //1.3
        if (setFun.size() != vecFun.size())
        {
            vecFun.push_back(it->second(dim));
        }
    }

    //2.
    return vecFun;
}

mapFun_t Test::getFunMap()
{
    mapFun_t mapFun
    {
        {FunType_E::Hard5_1_E, std::bind(initFunByHard5_1, std::placeholders::_1)},
        {FunType_E::EasyAny_1_E, std::bind(initFunByEasyAny_1, std::placeholders::_1)},
        {FunType_E::CEC2017_F1_E, std::bind(initFunByCEC2017_F1, std::placeholders::_1)},
        {FunType_E::CEC2017_F2_E, std::bind(initFunByCEC2017_F2, std::placeholders::_1)},
        {FunType_E::CEC2017_F3_E, std::bind(initFunByCEC2017_F3, std::placeholders::_1)},
        {FunType_E::CEC2017_F4_E, std::bind(initFunByCEC2017_F4, std::placeholders::_1)},
        {FunType_E::CEC2017_F5_E, std::bind(initFunByCEC2017_F5, std::placeholders::_1)},
        {FunType_E::CEC2017_F6_E, std::bind(initFunByCEC2017_F6, std::placeholders::_1)},
        {FunType_E::CEC2017_F9_E, std::bind(initFunByCEC2017_F9, std::placeholders::_1)},
        {FunType_E::NIST_Gauss3_E, std::bind(initFunByNIST_Gauss3, std::placeholders::_1)},
    };

    return mapFun;
}

std::shared_ptr<BaseFun> Test::initFunByEasyAny_1(std::size_t dim)
{
    return std::make_shared<EasyFunAny_1>(dim);
}

std::shared_ptr<BaseFun> Test::initFunByHard5_1([[maybe_unused]] std::size_t dim)
{
    return std::make_shared<HardFun5_1>();
}

std::shared_ptr<BaseFun> Test::initFunByCEC2017_F1(std::size_t dim)
{
    return std::make_shared<CEC2017_F1>(dim);
}

std::shared_ptr<BaseFun> Test::initFunByCEC2017_F2(std::size_t dim)
{
    return std::make_shared<CEC2017_F2>(dim);
}

std::shared_ptr<BaseFun> Test::initFunByCEC2017_F3(std::size_t dim)
{
    return std::make_shared<CEC2017_F3>(dim);
}

std::shared_ptr<BaseFun> Test::initFunByCEC2017_F4(std::size_t dim)
{
    return std::make_shared<CEC2017_F4>(dim);
}

std::shared_ptr<BaseFun> Test::initFunByCEC2017_F5(std::size_t dim)
{
    return std::make_shared<CEC2017_F5>(dim);
}

std::shared_ptr<BaseFun> Test::initFunByCEC2017_F6(std::size_t dim)
{
    return std::make_shared<CEC2017_F6>(dim);
}

std::shared_ptr<BaseFun> Test::initFunByCEC2017_F9(std::size_t dim)
{
    return std::make_shared<CEC2017_F9>(dim);
}

std::shared_ptr<BaseFun> Test::initFunByNIST_Gauss3([[maybe_unused]] std::size_t dim)
{
    return std::make_shared<NIST_Gauss3>();
}

}